using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework;

namespace Brain
{
    public class TouchMenuSystem : Brain.IUpdateable, Brain.IDrawable, IBaseComponent
    {
        public List<ITouchMenuEntry> Entries { get; set; }

        public bool ShouldUpdate { get; set; }
        public bool ShouldDraw { get; set; }

        public ITouchMenuAnimation Animation { get; set; }

        public int TimeToSelect = 300;

        public TouchMenuSystem()
        {
            Entries = new List<ITouchMenuEntry>();

            ShouldDraw = true;
            ShouldUpdate = true;

            TouchPanel.EnabledGestures |= GestureType.Tap | GestureType.FreeDrag;
        }
        public TouchMenuSystem(GameScreen gs)
            : this()
        {
            gs.AddComponent(this);
        }

        public void AddEntry(ITouchMenuEntry entry)
        {
            this.Entries.Add(entry);
        }

        /// <summary>
        /// The Entry the user put his finger,
        /// but didn't select
        /// </summary>
        protected ITouchMenuEntry selectedEntry;
        /// <summary>
        /// The time the entry has been selected
        /// </summary>
        protected int selectionTimer;
        public void Update()
        {
            for (int i = 0; i < this.Entries.Count; i++)
            {
                ITouchMenuEntry entry = this.Entries[i];
                if (entry is IUpdateable)
                {
                    IUpdateable up = entry as IUpdateable;
                    if (up.ShouldUpdate)
                    {
                        up.Update();
                    }
                }

                if (selectedEntry == null)
                {
                    selectionTimer = 0;

                    foreach (GestureSample sample in Engine.Instance.InputManager.Gestures)
                    {
                        Vector2 pos = sample.Position;
                        /*
                        if (Engine.Instance.RenderManager2D.CustomResMatrix != null)
                        {
                            pos = Vector2.Transform(pos, Matrix.Invert(Engine.Instance.RenderManager2D.CustomResMatrix.Value));
                        }*/
                        Rectangle t = new Rectangle((int)pos.X, (int)pos.Y, 1, 1);

                        if (entry.SelectionArea.Intersects(t))
                        {
                            if (sample.GestureType == GestureType.Tap &&
                                sample.GestureType != GestureType.FreeDrag)
                            {
                                selectedEntry = entry;
                            }
                            if (Animation != null)
                            {
                                Animation.Selected(entry);
                            }
                        }
                        else
                        {
                            if (Animation != null)
                            {
                                Animation.NotSelected(entry);
                            }
                        }
                    }

                    /// There might be no Gestures on screen, but the user might be with his finger
                    /// on-screen. So we add the amount of touches,
                    /// to certify the user is REALLY with nothing on the screen.
                    /// * Not adding the Touches count causes flick, because the gesture is only recorded
                    ///   when the user is still doing it
                    /// * Not looking if the user is still with fingers on screen won't
                    ///   remove the animation. So, if the user removes the finger off the screen while
                    ///   holding a button, the button will stay on the Animation.Selected(entry).
                    ///   In my example, the button keeps Yellow
                    if (Animation != null)
                    {
                        int gestures = Engine.Instance.InputManager.Gestures.Count + Engine.Instance.InputManager.Touches.Count;
                        if (gestures == 0)
                        {
                            Animation.NotSelected(entry);
                        }
                    }
                }
                else
                {
                    selectionTimer += Engine.Instance.GameTime.ElapsedGameTime.Milliseconds;
                    if (Animation != null)
                    {
                        Animation.Selected(selectedEntry);
                    }

                    if (selectionTimer > TimeToSelect)
                    {
                        selectedEntry.Clicked();

                        selectionTimer = 0;
                        selectedEntry = null;
                    }
                }
            }
        }
        
        public void Draw()
        {
            for (int i = 0; i < this.Entries.Count; i++)
            {
                ITouchMenuEntry entry = this.Entries[i];
                if (entry is IDrawable)
                {
                    IDrawable up = entry as IDrawable;
                    if (up.ShouldDraw)
                    {
                        up.Draw();
                    }
                }
            }
        }

        public bool ShouldSerialize
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public void SerializeData(SerializationData parentData, string index)
        {
            throw new NotImplementedException();
        }

        public void DeserializeData(SerializationData parentData, string index)
        {
            throw new NotImplementedException();
        }

        public string Name
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }


        public void DeserializedAll()
        {
            throw new NotImplementedException();
        }
    }
}
